package com.awakening.sorting.util;

import java.lang.reflect.Method;

/**
 * 随机生成算法测试类——本案例以int类型
 * @Author:AwakeningCode
 * @Date: Created in 9:22 2018\1\17 0017
 */
public class SortTestHelper {

    //SortTestHelper不允许产生任何实例
    private SortTestHelper(){}

    //生成有n个元素的随机数组，每个元素的随机范围为[rangeL,rangeR]
    public static Integer[] generateRandomArray(int n,int rangeL,int rangeR){
        assert rangeL <= rangeR;
        Integer[] arr = new Integer[n];
        for (int i = 0 ; i < n ;i ++){
            arr[i] = new Integer((int)(Math.random() * (rangeR - rangeL +1) + rangeL));
        }
        return arr;
    }

    /**
     * 生成一个近乎有序的数组
     * 首先生成一个含有[0...n-1]的完全有序数组，之后随机交换swapTimes对数据
     * @param n
     * @param swapTimes 定义了数组的无序程度、其等于0时，数组完全有序、其值越大，数组越趋向于无序
     * @return
     */
    public static Integer[] generateNearlyOrderedArray(int n,int swapTimes){
        Integer[] arr = new Integer[n];
        for(int i=0;i<n;i++){
            arr[i] = new Integer(i);
        }
        for (int i =0;i<swapTimes;i++){
            int a = (int)(Math.random()*n);
            int b = (int)(Math.random()*n);
            int t = arr[a];
            arr[a] = arr[b];
            arr[b] = t;
        }
        return arr;
    }

    //打印arr数组的所有内容
    public static void printArray(Object arr[]){
        for (int i = 0;i < arr.length; i ++){
            System.out.print(arr[i]);
            System.out.print(' ');
        }
        System.out.println();
        return;
    }

    //判断arr数组是否有序
    public static boolean isSorted(Comparable[] arr){
        for (int i = 0 ;i < arr.length ; i ++){
            if (arr[i].compareTo(arr[i+1]) > 0){
                return false;
            }
        }
        return true;
    }

    //测试sortClassName所对应的排序算法排序arr数组所得到的的正确性和算法运行时间
    public static void testSort(String sortClassName, Comparable[] arr){
        // 通过Java的反射机制，通过排序的类名，运行排序函数
        // * 依然是，使用反射机制并不是这个课程的重点, 大家也完全可以使用自己的方式书写代码, 最终只要能够测试出自己书写的算法的效率即可
        try {
            //通过sortClassName获得排序函数的Class对象
            Class sortClass = Class.forName(sortClassName);
            //通过排序函数的Class对象获得排序方法
            Method sortMethod = sortClass.getMethod("sort",new Class[]{Comparable[].class});
            //排序参数只有一个，是可比较的数组arr
            Object[] params = new Object[]{arr};
            long startTime = System.currentTimeMillis();
            //调用排序函数
            sortMethod.invoke(null,params);
            long endTime = System.currentTimeMillis();

            assert isSorted(arr);

            System.out.println(sortClass.getSimpleName() + ":" + (endTime - startTime) + "ms");
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}
